-module(my_net_svr).
-behaviour(gen_server).
-export([start_link/1, stop/0, init/1, terminate/2, code_change/3, handle_cast/2, handle_info/2, handle_call/3 ]).
-export([start_listen/1]).
-include("common.hrl").

-record(state, {sock = 0}).
%%--------------------------------------------------------------------
start_link(Data) ->
    gen_server:start_link({global, my_net}, ?MODULE, Data, []).

stop() ->
    gen_server:cast(?MODULE, stop).

init([Port]) ->
	erlang:start_timer(100, self(), {?MODULE,start_listen,Port}),
	{ok, #state{}}.

start_listen(Port) ->
	?log("start_listen,Port = ~p",[Port]),
	try
		case gen_tcp:listen(Port, ?TCP_OPTIONS) of
			{ok, Sock} ->
				gen_server:cast(self(), {do_accept,Sock});
			{error, Reason} ->
				?log("start_listen,error,Reason = ~p",[Reason]),
				gen_server:cast(self(), {listen_fail,Reason})
		end
	catch E:R -> ?log("start_listen,error,e = ~p,r=~p",[E,R])
	end.

do_accept(Sock) ->
	case gen_tcp:accept(Sock,100) of
		{ok, Socket} ->
			inet:setopts(Socket, [binary, {active, true}]),
			Pid = my_net_sup:add(Socket),
			gen_tcp:controlling_process( Socket, Pid ),
			ok;
		{error, timeout} ->ok;
		{error, Reason} ->
			?log_error("accept error, Reason = ~p ~n", [Reason]),
			{error, Reason}
	end.  
terminate(_Reason, #state{}) ->
    ok.

code_change(_OldVsn, State, _Extra) ->    
    {ok, State}.

handle_call(_Request, _From, State) ->    
    {reply, ok, State}.

handle_info({timeout, _TimerRef, CallBackInfo},State) ->
	case CallBackInfo of
		{Module, Function} ->
			try
				Module:Function()
			catch E:R ->?log_error("timeout error,data=~p,E=~p,R=~p,stack=~p",[CallBackInfo,E,R,erlang:get_stacktrace()])
			end;
		{Module, Function, Args} ->
			try
				Module:Function(Args)
			catch E:R ->?log_error("timeout error,data=~p,E=~p,R=~p,stack=~p",[CallBackInfo,E,R,erlang:get_stacktrace()])
			end;
		_ ->
			?log_warning("unknown timer callback,CallbackInfo=~p", [CallBackInfo])
	end,
	{noreply, State};
handle_info(_Request, State) ->
    {noreply, State}.

handle_cast({listen_fail,Reason},State) ->	
	{stop,{listen_fail,Reason},State};
handle_cast({do_accept},State = #state{sock = Sock}) ->
	case do_accept(Sock) of
		{error, Reason} -> {stop,{accept_fail,Reason},State};
		_ ->
			gen_server:cast(self(), {do_accept}),
			{noreply, State}
	end;
handle_cast({do_accept,Sock},State) ->
	?debug("do_accept"),
	case do_accept(Sock) of
		{error, Reason} -> {stop,{accept_fail,Reason},State#state{sock = Sock}};
		_ ->
			gen_server:cast(self(), {do_accept}),
			{noreply, State#state{sock = Sock}}
	end;
handle_cast(stop, State) ->
    {stop, normal, State};

handle_cast(_Request, State) ->
	?log_error("unmatch _Request=~p",[_Request]),
    {noreply, State}.


